package br.com.afi.pattern.repository;

import java.io.Serializable;
import java.util.List;

import br.com.afi.pattern.model.Model;

/**
 * Essa interface possui os métodos genéricos para repositórios.
 *
 * @author André de Fontana Ignacio
 * @version 1.0
 * @param <E> Tipo da entidade
 * @param <ID> Tipo da chave primária da entidade.
 */
public interface GenericRepo<E extends Model<ID>, ID extends Serializable> 
{
	/**
	 * Obtém a quantidade total de entidades
	 * 
	 * @return Quantidade de entidades
	 */
	Number count();

	/**
	 * Obtém uma entidade.
	 * 
	 * @param id Chave primária
	 * @param lock Se verdadeiro, trava a tabela para execução de updates.
	 * @return Entidade
	 */
	E get( ID id, boolean lock );
	
	/**
	 * Obtém uma entidade através da sua chave primária.
	 * 
	 * @param id Chave primária
	 * @return Entidade
	 */
	E get( ID id );

	/**
	 * Busca todos as entidades.
	 * 
	 * @return Lista de entidades
	 */
	List<E> get();

	/**
	 * Obtém as entidades utilizando paginação.
	 * 
	 * @param firstResult Número do primeiro registro.
	 * @param maxResults Número máximo de registros.
	 * @return Lista de entidades
	 */
	List<E> get( int firstResult, int maxResults );

	/**
	 * Verifica se existe alguma entidade através do Id informado.
	 * 
	 * @param id Id
	 * @return Verdadeiro se existir
	 */
	boolean contains( ID id );

	/**
	 * Obtém a quantidade de entidades buscando pela instância de exemplo informada.
	 * 
	 * @param exampleInstance Instância de exemplo
	 * @param excludeProperty Propriedades a serem desconsideradas na busca
	 * @return Lista de entidades
	 */
	Number countByExample( E exampleInstance, String... excludeProperty );

	/**
	 * Obtém a quantidade de entidades buscando pela instância informada utilizando like.
	 * 
	 * @param exampleInstance Instância de exemplo
	 * @param includeRelationships Incluir relacionamentos na busca?
	 * @param excludeProperty Propriedades a serem desconsideradas durante na busca
	 * @return Lista de entidades
	 */
	Number countByExampleILike( E exampleInstance, boolean includeRelationships, String... excludeProperty );

	/**
	 * Busca através de instância de exemplo.
	 * 
	 * @param exampleInstance Instância de exemplo
	 * @param excludeProperty Propriedades a serem desconsideradas durante na busca
	 * @return Lista de entidades
	 */
	List<E> findByExample( E exampleInstance, String... excludeProperty );

	/**
	 * Busca por um instância de exemplo utilizando like.
	 * 
	 * @param exampleInstance Instância de exemplo
	 * @param excludeProperty Propriedades a serem desconsideradas durante na busca
	 * @return Lista de entidades
	 */
	List<E> findByExampleILike( E exampleInstance, String... excludeProperty );

	/**
	 * Busca por um instância de exemplo utilizando insensitive like.
	 * 
	 * @param exampleInstance Instância de exemplo
	 * @param includeRelationships Incluir relacionamentos na busca?
	 * @param excludeProperty Propriedades a serem desconsideradas durante na busca
	 * @return Lista de Entitys
	 */
	List<E> findByExampleILike( E exampleInstance, boolean includeRelationships, String... excludeProperty );

	/**
	 * Busca por um instância de exemplo utilizando insensitive like e paginação
	 * 
	 * @param exampleInstance Instância de exemplo
	 * @param includeRelationships Incluir relacionamentos na busca?
	 * @param firstResult Número do primeiro registro
	 * @param maxResults Número máximo de registros
	 * @param excludeProperty Propriedades a serem desconsideradas durante na busca
	 * @return Lista de Entitys
	 */
	List<E> findByExampleILike( E exampleInstance, boolean includeRelationships, int firstResult, int maxResults, String... excludeProperty );
	
	/**
	 * Adiciona uma entity ao repositório.
	 * 
	 * @param entity Entidade
	 * @return Entidade
	 */
	E add( E entity );

	/**
	 * Remove uma entity do repositório.
	 * 
	 * @param entity Entidade
	 */
	void remove( E entity );
}
